코어자바 1장

  1. 자바는 객체 지향 언어이므로 프로그램에서 (대부분) 객체를 조작해 일을 시킨다. 각 객체는 클래스에 속하며, 그 객체를 클래스의 인스턴스라고 한다. 클래스에는 객체 상태와 할 수 있는 일을 정의한다. 자바는 모든 코드를 클래스 안에 정의한다.
  2. main 메서드는 프로그램을 실행할 때 첫 번째로 호출하는 메서드다. 이 메서드는 객체가 없어도 작동하도록 static으로 선언한다.
  3. 클래스를 패키지 안에 넣어 관련있는 클래스들을 함께 묶어 이름이 같은 클래스가 여러 개 있더라도 서로 충돌하지 않게 하면 좋다.
  4. 자바는 클래스, 패키지, 모듈로 구조화해 대규모 프로그램을 개발하기 좋은 언어이다.
  5. 자바 프로그램을 컴파일하고 실행하려면 JDK를 설치해야한다.
  6. 자바 프로그램은 두단계에 거쳐 실행된다

    1. javac 명령으로 자바 소스코드를 특정 기계에 종속되지 않은 중간 표현인 바이트 코드로 컴파일 해서 클래스 파일에 저장한다.
    2. java 명령으로 가상머신을 구동하고 클래스 파일을 로드해서 바이트 코드를 실행한다.
  7. 바이트 코드는 한번 컴파일하면 모든 자바 가상머신에서 실행할 수 있다.
  8. System.out은 객체이며, PrintStream 클래스의 인스턴스이다. 그 안에 println, print 메서드 등이 존재한다. 이해당 클래스의 객체(인스턴스)에서 작동하는 메서드를 인스턴스메서드라고 한다.
  9. 자바는 객체 대부분을 생성해야 한다. new 연산자로 생성하며 new classname(인자값)으로 생성한다.
  10. 한 객체에서 메서드를 두 번 이상 호출하기 위해선 변수에 저장해야된다.
  11. JShell : REPL(Read-Evaluate-Print-Loop)로 자바 표현식을 입력하면 평가해서 결과를 출력하고 다음입력을 기다리는 프로그램이다.
  12. 자바는 객체지향이지만 그렇다고 다 객체 지향인것은 아니다

    • primitive type : 기본 타입 네가지(byte, short, ing, long)는 부호 있는 정수 타입이고, 두 가지(float, double) 부동소수점 타입이며, 하나는 문자열 인코딩에 사용하는 문자타입인 char, 나머지 하나는 진리값 boolean타입이다.

      • byte Ehsms short타입은 주로 저수준 파일 처리 등 특수한 응용이나 저장 공간이 귀할 때 큰 배열을 만드는 용도로 사용한다.
      • long type으로 충분하지 않을땐 BigInteger 클래스를 사용한다.
      • 자바의 정수타입 범위는 프로그램 실행하는 머신과 상관없이 동일하다.
      • C 또는 C++로 작성한 프로그램은 컴파일 하는 프로세서에 따라 정수 타입이 다르다.
      • long 정수 리터럴은 L을 붙여서 작성한다. byte는 (byte)127 처럼 캐스트표기법을 사용한다.
      • 16진수 리터럴에는 접우더 0x를 붙인다. 2진수는 0b를 붙힌다.
      • 숫자 리터럴은 ”_“를 사용할 수 있으며 사람이 구분하는 용도이고 컴파일 할땐 밑줄을 삭제한다.
      • float 타입 숫자에는 접미어 F를 붙인다. 3.14 처럼 부동 소수점 리터럴에 접미어를 붙이지 않으면 double 타입이 된다.
      • double에서 무한대는 Double.POSITIVE_INFINITY로 나타내고 숫자가 아님은 Double.Nan등 특별한 부동 소수점 값이 있다.
      • 부동 소수점 타입은 반올림 오류가 있어서 정확한 숫자 계산이 필요할 때는 BigDecimal 클래스를 사용해야한다.
  13. char 타입은 자바가 사용하는 UTF-16 문자 인코딩의 코드 유닛을 나타낸다.

    • 작은 따옴표로 리터럴을 표시할 수 있다.
    • 특수코드 \n: line feed \r: carriage return \t: tab \b: backspace 가 있다.
    • 백 클래시 또는 작은 따옴표를 나타낼 때는 앞에 \를 붙힌다.
  14. boolean은 숫자 타입이 아니며 0과 1사이에는 관련없다.
  15. 자바는 타입 결합이 강한 언어라서 변수에는 해당 타입 값만 저장할 수 있다. 변수를 선언할 때는 타입과 이름을 지정해야되며 필요하면 초기값도 지정할 수 있따.
  16. 객체 생성은 new 표현식으로 한다.
  17. 변수 이름은 문자로 시작해야하며 문자,숫자,기호_과 $로 구성되지만 $는 자동 생성되는 이름용으로 직접 이름을 지을때는 사용하지 않는다.
  18. 보통 변수와 메서드의 이름은 소문자로 시작하고 클래스이름은 대문자로 시작하며 낙타 표기법을 선호한다.
  19. 메소드 안에 변수를 선언했다면 변수를 반드시 초기화 후에 사용해야한다.
  20. 자바에서는 변수를 사용하기 직전까지 변수 선언 시기를 늦추는 것을 좋은 방식으로 여긴다.
  21. final 키워드는 한번 할당하면 변경할 수 없는 값에 사용한다. 상수는 보통 변수를 대문자로 선언안다. static 키워드로 상수를 메서드 외부에 선언할 수 있다.

    • 하지만 System.out처럼 상수에 대문자를 쓰지 않는 몇가지가 존재한다.
  22. final은 값을 할당하면 최종 값이 되어 절대로 변경할 수 없는 뜻으로, 할당하기 전까지 초기화를 나중으로 미룰 수 있다.
  23. 서로 관련있는 상수의 집합을 enumerated type으로 정의할 수 있다.

    • class 이다.
    • static이다.

입출력

입력 읽어오기

System.out.println을 호출하면 출력이 표준 출력 스트립(standard output strea)으로 전달되어 터미널에 표현된다. 하지만 표준 입력 스트림(standard input stream)의 System.in 객체에는 바이트 한개를 읽어오는 메서드만 있기 때문에 문자열과 숫자를 읽기 위해선 System.in에 연결된 Scanner를 생성해야한다.

입력에 공백이 필요한 경우엔 nextLine메서드를, 공백으로 구분된 단어 한개를 익기 위해선 next() 메서드를 호출하여 사용할 수 있다. 수치를 받는 메서드로 nextInt(), nextDouble() 메서드가 있다.

Scanner in = new Scanner(System.in);

String includingEmpty = in.nextLine();

String oneWord = in.next();

String getInteger = in.nextIn();

다른 줄, 단어, 정수, 부동 소수점 수가 있는지 검사하고 싶을때는 hasNextLine, hasNext, hasNextInt, hasNextDouble 메서드를 사용하면 된다.

if (in.hasNextInt()) {
    int ageg = in.nextInt();
}

Scanner 클래스를 사용하면 입력 내용이 터미널에 보이므로 비밀번호를 읽을때는 Console 클래스를 이용해야한다. 하지만 ide로 실행할 경우 console 장치가 없기 대문에 null값을 반환한다.

포맷 적용 출력

포맷 문자열(format string) “%8.2f는 부동소수점 수를 필드 폭(field width)은 8자리로 출력하고, 정밀도(precision)는 2자리로 출력한다.

System.out.printf("%8.2f", 1000.0 / 3.0);

String message = String.format("Hello, %s. Next year, you'll be %d.\n", name, age);

% 문자로 시작하는 포맷 지정자(format specifier)는 각각에 대응하는 인수로 교체된다. 포맷 지정자 끝에 오는 변환 문자(conversion character)는 포맷이 적용될 값의 타입을 나타낸다.

String.format 메서드를 사용하면 포맷 적용 문자열을 출력하지 않고 만들 수 있다.

제어 흐름

분기

if 문은 괄호 안에 조건이 들어가고, 그 뒤에 한 문장 또는 중괄호로 감싼 문장 묶음이 온다.

if (count > 0) {
    double average = sum / count;
    System.out.println(average);
}

조건이 맞지 않을땐 실행할 분기를 else로 추가할 수 있다. else 분기에는 또 다른 if문을 둘 수도 있다.

if (count > 0 ) {
    double average = sum / count;
    System.out.println(average);
}else if(count == 0 ) {
    System.out.println(0);
} else {
    system.out.println(0);
}

제한된 개수의 상수 값을 기준으로 표현식을 검사할 때는 switch 문을 사용한다. 일치하는 case 레이블을 실행하고, 일치하는 케이스가 없을 경우 default 레이블을 실행한다. 실행을 시작하면 breaksk switch문의 끝에 이르기 전까지 있는 모든 문장을 실행해야한다.

switch (count) {
    case 0:
        output = "None";
        break;
    case 1:
        output = "One";
        break;
    case 2:
    case 3:
    case 4:
    case 5:
        output = Integer.toString(count);
        break;
    default:
        output = "Many";
        break;
}

case 레이블에는 다음 타입값을 사용할 수 있다.

  • char, byte, short, int(Wrapper 클래스도 포함) 상수 표현식
  • 문자열 리터럴
  • 열거 값.

while 루프

while 루프는 조건 검사 결과에 따라 수행할 작업이 남아 있는 동안 바디를 계속 실행한다.

Random gen = new Random(10);

while (sum < target) {
    int next = gen.nextInt(10);
    sum += next;
    count ++;
}

조건을 평가하기 전에 루프 바디(구현부)를 실행해야 할 때도 있다. do/While 루프를 사용한다.

int next;

do {
    next = gen.nextInt(10);
    count ++;
} while(next != target);

for문

while은 루프의 반복 횟수를 알수가 없다. 반복 횟수가 고정되어져 있을 땐 for 루프를 사용한다.

for (int i= 1; i <=20; i++) {
    int next = gen.nextInt(10);
    sum += next;
}

forwhile로 바꿔 쓸 수 있지만, i 변수의 초기화, 검사, 업데이트가 따로 흩어지며 for문 사용하여 나란히 둘 수 있다.

```java
int i = 1;
while(i <= 20) {
    int next = gen.nextInt(10);
    sum += next;
    i++;
}

for 루프의 헤더에서 변수를 선언하는 대신 기존 변수를 초기화 해도 되며, 초기화, 검사, 업데이트를 콤마를 사용하여 여러 변수를 초기화 검사 업데이트를 할 수 있다. 또 초기화나 업데이트가 필요없으면 비워둬도 되며 조건을 생략하면 항상 true로 간주하여 무한 루프를 수행한다.

for (int i = 1; i < target; i *=2 ) {
    System.out.println(i;)
}

//외부에서 초기화.
int i;
for (i = 1; i < target; i*= 2)

//콤마를 사용한 여러개의 초기화, 검사, 업데이트
for ( int i = 0, j = n - 1; i < j; i++,j--)

//초기화나 업데이트가 필요없으면 비워두고, 조건을 생략하면 항상 true로 무한루프
for (;;)

break continue

루프를 중간에 빠져나오기 위해선 break문을 사용한다. break 문에 이르면 즉시 빠져나온다.

continue문은 break와 유사하지만 루프의 끝이 아니라 현재 루프 반복의 끝으로 건너뛴다. for loop 안에서 사용하면 그다음 업데이트 문장으로 건너 뛴다.

break 문은 자신을 직접 감싼 루프 또는 switch문만 빠져나오게 한다. 감싸고 있는 또 다른 문장의 끝으로 건너뛰려면 레이블을 붙인(labeled) break 문을 사용해야한다. 레이블은 문장의 윗쪽에 붙이지만, break 문은 해당 문장의 끝으로 건너뛴다.

outer:
while(...) {
    ...
    while (...) {
        ...
        if (...) break outer;
    }
}

일반적인 break는 루프나 switch를 빠져나오는 용도로만 사용할 수 있지만, 레이블을 붙인 break는 블록 문을 포함해서 어떤 문장의 끝으로든 제어를 이동할 수 있다.

exit: {
    ...
    if (...) break exit;
    ...
}

continue에 label을 붙힌다면, 이는 레이블을 붙인 루프의 다음 번 반복으로 건너뛰게한다. 밑의 코드는 5를 출력하지 않는다.

int w = 0;
point:
while (true) {
    w++;
    if (w == 5) continue point;

    if(w==20) {
        break point;
    }
    System.out.println(w);
}

지역 변수의 유효 범위

지역 변수(local variable)는 메서드의 매개변수를 포함해 메서드 안에 선언한 변수다. 변수의 유효 범위(scope)는 프로그램에서 해당 변수에 접근할 수 있는 부분이다. 지역 변수의 유효 범위는 변수 선언 지점에서 시작해 해당 선언을 감싼 블록의 끝까지 이어진다. 다시말해 루프가 반복될 때마다 input의 사본을 새로 만들며, 루프 바깥쪽에는 input 변수가 존재하지 않는다. 매개 변수의 유효 범위는 메서드 전체다.

두번째 코드는 next를 while 밖에 선언하여 next에 누적 합을 구하고 있다. 유효범위를 잘 보자.

while (...) {
    System.out.println(...);
    String input = in.next; //여기서 input의 유효 범위가 시작된다.
    ...
    //여기서 input의 유효 범위가 끝난다.
}

int next;
do {
    next = gen.nextInt(10);
    count ++;
} while (next != target);

for 문도 동일하며, 루프가 끝난 뒤에서 i값이 필요하다면 변수를 루프 바깥쪽에 선언해야한다.

int i;
for (i = 0; !fount && i < n; i++) {
    ...
}
//밖에서도 i는 여전히 사용이 가능하다.

자바에서는 서로 겹치는 유효 범위에 이름이 같은 지역 변수를 여러 개 둘 수 없다.

int i = 0;
while(...) {
    String i = in.next();   //또 다른 변수를 선언하는 것은 에러가 발생
}

유효 범위가 겹치지 않는다면 변수 이름이 같아도 재사용할 수 있다.

for (int i = 0; i < n / 2; i ++) {...}
for (int i = n / 2; i < n; i ++)  {...}

배열과 배열 리스트(Array)

배열은 프로그래밍의 기본 요소로 타입이 같은 아이템(항목)을 모으는 데 사용한다. 자바는 언어수준에서 배열 타입을 포함하며, 필요에 따라 늘어다고 줄어드는 배열을 나타내는 ArrayList 클래스도 제공한다.

배열 사용하기

모든 타입에는 대응하는 배열 타입이 있다. 정수의 배열은 int[]타입, String 객체의 배열은 String[]타입이 되는 식이다.

String [] names;

배열을 초기화 하기 위해선 new 연산자가 필요하다. 선언과 동시에 초기화가 가능하다. 또 배열을 접근하기 위해선 names[1]과 같이 접근할 수 있다.

names = new String[100];

String[] names = new String[100];

names[1] = "String";

배열 생성

new 연산자로 배열을 선언하면 배열을 기본 값으로 채운다.

  • 숫자타입(char을 포함)의 배열은 0으로 채운다.
  • boolean의 배열은 false로 채운다.
  • 객체의 배열은 null 참조로 채운다.

하지만 초기화 할 값을 알고 있을 경우, 초기화와 동시에 중괄호 안에 원하는 값을 나열하면 된다.

int[] primes = {2, 3, 5, 7, 11, 13};

중괄호로 값을 채울 때 new 연산자를 사용하지 않으며 배열의 길이도 지정하지 않는다. 마지막 요소 뒤에 쉼표를 넣어도 되는데 이렇게 하면 배열에 값을 계속 추가해 나갈 때 편리하다.

String[] authors = {
    "James Gosling",
    "Bill Joy",
    "Guy Steele",
    //여기에 저자 이름을 추가하고 각 이름 뒤에 콤마를 붙인다.
}

배열에 이름을 붙이지 않을때도 이와 같은 유사한 초기화 문법을 사용하지만, new 연산자와 타입을 중괄호 앞에 붙혀줘야한다.

primes = new int[] {17,19,23,29,31}

길이가 0인 배열도 만들 수 있으며 길이가 0 인 배열과 null은 다르다.

new int[0];
new int[]{};

ArrayList

배열은 생성하려면 길이를 알아야하고, 한번 생성하면 길이를 변경할 수 없다. 이 문제를 해결하기 위해서 ArrayList 객체는 내부에서 배열을 관리한다. 배열이 너무 작아지거나 배열의 공간이 많이 남으면, 다른 내부 배열을 자동으로 생성해서 원본 배열의 요소를 옮긴다. 동작방식에 대한 자세한 내용은 다음번에 다루도록 하자.

배열은 특수 문법을 사용한다. 요소에 접근할 때는 [] 연산자를 사용하고, 배열 타입에는 Type[] 문법, 배열을 생성할 때는 new Type[n] 문법을 사용한다. 이와달리 배열 리스트는 클래스이므로 일반 인스턴스 생성 문법과 메서드 호출 문법을 사용한다.

ArrayList는 generic class가 있으며, 즉 타입 매개변수가 있는 클래스이다. 그렇기 대문에 ArrayList를 선언하기 위해선 제네릭 클래스 문법을 사용해(<>) 안에 타입을 지정해야한다. 또 <> 부분이 비어 있다면 컴파일러가 변수의 타입에서 타입 매개변수를 추론하기 때문에 비울 수 있다. 생성을 위한 호출에는 인수가 없어도 ()를 뒤에 붙혀줘야한다.

ArrayList<String> friends;

ArrayList<String> friends = new ArrayList<>();

ArrayList 초깃값 지정 문법은 없지만, List.of(“peter”,“Paul) 을 사용하여 배열 리스트를 생성하는것이 최선이다. List.of 메서드는 지정한 요소들로 구성된 수정 불가능한 리스트를 반환한다.

ArrayList<String> friends = new ArrayList<>(List.of("Peter","Paul"));

ArrayList의 요소에 접근하기 위해선 get, set메소드를 사용한다.

기본 타입의 래퍼 클래스

제네릭 클래스에는 기본타입을 사용할 수 없다. ArrayList<int>는 규칙에 어긋난다. 해결책으로 래퍼 클래스(wrapper class)를 이용한다.

ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(42);

//위의 코드는 이와같이 컴파일러가 변환하여 수행한다.
numbers.add(Integer.valueOf(i));


int first = numbers.get(0);
//위의 코드는 이와같이 컴파일러가 변환하여 수행한다.
int first = numbers.get(0).intValue();

기본 타입과 그에 대응하는 래퍼 타입 사이의 변환은 자동으로 일어난다. add를 호출하는 과정에 autoboxing을 거쳐 42는 Integer 객체를 자동으로 만든다. get 호출은 Integer를 반환한다. int 변수에 할당하기 앞서 이 객체는 내부의 int 값을 돌려주도록 unboxing된다. 컴파일러는 이를 확인하여 자동으로 위와 같은 변환을 수행한다.

wrapper 타입의 동일성을 비교하기 위해선 primitive와 같은 == 가 아니라 equals() 메서드를 사용해야 한다.

향상된 for fnvm

향상된 for 루프의 변수는 배열의 인덱스 값이 아니라 요소를 순회한다. 이것으로 볼때 iterator또는 generator를 사용한 것 같다.

for (String name: friends) {
    System.out.println(name);
}

배열과 배열 리스트 복사

int[]numbers = primes;
numbers[5] = 42;    //primes[5] 도 이제 42다.

위와같은 문제를 방지하기 위해 Arrays.copyOf 메서드를 사용하여 배열의 사본을 만들어야 한다. 이 메서드는 새 배열을 원하는 생성하고 배열의 요소를 복사한다.

int[] copiedPrimes = Arrays.copyOf(primes, primes.length);

ArrayList를 복사하려면 기존 배열 리스트에서 새 배열 리스트를 생성해야한다. 밑의 코드는 새로운 ArrayList를 생성하면서, abstractList를 상속받는 ArrayList 자신을 입력값으로 넣어 초기화 하고 있다. 배열을 배열 리스트에 복사할 때는 Listof 메서드를 사용하여 배열을 불변 리스트로 감싸서 사용하면 된다. 하지만 이부분은 안된다.. 왜그러는지 모르겠다.

ArrayList<String> copiedFriends = new ArrayList<>(friends)

String names = {"a","b","c","d"};
ArrayList<String> friends = new ArrayList<>(List.of(names));        //이부분 안된다.

배열 리스트를 배열에 복사할 수도 있다. 하위 호환성 때문에 반드시 올바른 타입으로 된 배열을 전달해야한다. toArray에 String 객체를 넣는 이유는 toArray에서 제네릭 타입을 사용하기 위해 String을 넣고있다.

String[] names = friends.toArray(new String[0]);

기본 타입 배열과 그에 대응하는 wrapper 클래스의 배열리스트를 상호 변환은 boxing과 unboxing 처리를 직접 해줘야 되기 때문에 문제가 된다. 그렇기 때문에 for문을 사용하여 boxing을 해주던지 아니면 Stream을 이용하여 처리할 수 있다.

       //page 78 의 note 부분 .
       int[] intArray = {1, 2, 3, 4, 5};

       //boxing, unboxing 처리 때문에 문제가 된다.
//        ArrayList<Integer> arrayList = new ArrayList<>(List.of(intArray));

       //이 방식을 쓰거나.
       ArrayList<Integer> arrayList = new ArrayList<>(intArray.length);
       for (int item : intArray) {
           arrayList.add(item);
       }
       for (Integer item : intArray) {
           System.out.println("intArray  : "+item);
       }


       ArrayList<Integer> arrayList1 = new ArrayList<>(Arrays.stream(intArray).boxed().collect(Collectors.toList()));
       for (Integer item : arrayList1) {
           System.out.println("intArray1 : "+item);
       }

배열 알고리즘

Arrays.fill(numbers, 0 ); 은 배열의 원소를 채워 넣는 것이고, Collections.fill(friends, ""); 는 ArrayList의 값을 ""로 채워넣는 것이다.

Array.fill(numbers, 0);
Collections.sort(friends);

배열에는 parallerSort 메서드를 사용하여 배열이 클 경우 프로세서를 나눠서 소트가 가능하다.

numbers.parallerSort();

Arrays.toString 메서드는 배열을 문자열로 표현한 결과를 돌려주며, ArrayList.toString 또한 동일한 표현을 반환한다.

System.out.println(Arrays.toString(primes));

System.out.println(arraylist.toString());

명령줄 인수

main 메서드는 문자열의 배열을 매개변수로 받는다. public static void main(String[] args) 명령어 java Greeting -g cruel world를 입력하면 옵션부터 args 배열로 받을 수 있다.

다차원 배열

자바는 다차원 배열(multidimensional array)가 없고 배열의 배열로 다차원 배열을 구현한다.

int[][] square = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12},
    {13, 14, 15, 16},
};

square[0][] 는 {1,2,3,4}를 가리키며, 요소를 얻기 위해 두 대괄호 쌍을 이용해서 접근한다. 초깃값을 제공하지 않을 때는 반드시 new 연산자를 사용하고 행과 열의 개수를 지정해야 한다.

다차원 배열을 이용하여 파스칼의 삼각형을 구현할 수 있다.

int n = 10;
int[][] triangle = new int[n][];

for (int i = 0; i < n ; i ++) {
    triangle[i] = new int[i + 1];
    triangle[i][0] = 1;
    triangle[i][i] = 1;
    for (int j = 1; i < i; j++) {
        triangle[i][j] = triangle[i - 1][j - 1] + triangle[i - 1][j];
    }
}

for (int r = 0; r < triangle.length; r ++) {
    for (int c = ; c < triangle[r].length; c++){
        System.out.printf("%fd", triangle[r][c]);
    }
    System.out.println();
}

디버깅을 위해 2차원 배열의 요소 목록을 출력하기 위해 Arrays.deepToString() 메서드를 사용한다.

기능적 분해

main 메서드가 너무 길어질 때는 프로그램을 여러 클래소르 분해하는것이 좋다. 간단한 프로그램이라면 코드를 동일한 클래스 안에서 여러 메서드로 나누어도 된다.

정적 메서드 선언 및 호출

메서드를 선언 할 때는 반환 값의 타입(or void), 메서드이름, 매개변수의 타입과 이름을 메서드 헤더에 작성하고, 구현부를 메서드 바디에 넣는다. 반환값이 있다면 return을 사용한다.

매개변수로 배열을 전달할 수 있고, 메서드는 배열에 대한 참조를 받으며, 이 참조로 전달 받은 배열을 변경할 수 있다.

메서드는 배열을 반환할 수 있다. 다음 메서드는 매개 변수로 받은 배열을 변경하지 않고, 첫 번째 값과 마지막 값으로 구성된 배열을 반환한다.

가변인수

타입이 동일한 변수 여러개를 매개변수로 연속해서 넣을 경우 …를 사용할 수 있다. 메서드 구현부에선 배열처럼 사용할 수 있다.

public static double average (double ...values) {
    double sum = 0;
    for (double v : values) sum +=v;
    return values.length == 0 ? 0 : sum / values.length;
}

인수들이 이미 배열 안에 있으면 풀어 쓸 필요 없이 배열로 전달할 수 있다.

double[] scores = {3, 4.5, -5, 0};
double avg = average(scores);

가변 매개변수는 반드시 메서드의 마지막 매개변수여야 한다. 하지만 다른 매개변수를 가변 매개변수 앞에 둘 수 있다.

public static double average (String a, double ...values) {
    double sum = 0;
    for (double v : values) sum +=v;
    return values.length == 0 ? 0 : sum / values.length;
}

Written by@Zero1
This blog is for that I organize what I study and my thinking, feeling and experience.

GitHub